<template>
  <div class="file-editor-container"
       :style="{ height: isDragging ? editorHeight + 'px' : '100%' }">
    <monaco-editor
      v-model="value"
      :language="language"
      theme="vs"
      :options="{
                fontSize: 14,
                lineNumbers: 'on',
                minimap: { enabled: true },
                scrollBeyondLastLine: false,
                automaticLayout: true
              }"
    />
    <div
      class="resize-handle"
      @mousedown="startResize"
    ></div>
  </div>
</template>

<script>
import MonacoEditor from 'monaco-editor-vue'
import * as monaco from 'monaco-editor'
import { throttle } from 'lodash'; // 引入 lodash 的 throttle 方法
export default {
  name: 'HCMonacoEditor',
  components: {
    MonacoEditor
  },
  props: {
    // 双向绑定值
    value: {
      type: String,
      required: false
    },
    // 报表组件配置
    ctrlProps: {
      type: Object,
      required: false,
      default: {
        fileName: '',
        language: ''
      }
    }
  },
  data() {
    return {
      language: 'plaintext',
      editorHeight: 0, // 编辑器真实高度（动态调整）
      initHeight: 0,   // 记录初始高度
      isDragging: false, // 是否正在拖拽
      isResizing: false, // 是否开始拖拽调整
      startY: 0, // 拖拽开始的鼠标 Y 坐标
      startHeight: 0, // 拖拽开始的初始高度
      // 支持的语言列表
      languageList: ['javascript', 'typescript', 'html', 'css', 'less',
        'scss', 'json', 'markdown', 'vue', 'python', 'java', 'xml', 'sql'],
    }
  },
  watch:{
    // 监听双向绑定值的变化
    value: {
      handler: function (newVal, oldVal)
      {
        this.$emit('input', newVal)
      },
      deep: true
    }
  },
  computed: {
    // 节流后的 resize 方法
    throttledResize() {
      return throttle(this.handleResize, 16); // 每 16ms 更新一次
    },
  },
  mounted() {
    this.language = this.ctrlProps.language || this.getFileLanguage(this.ctrlProps.fileName)
    // 注册 Monaco Editor 语言
    if (!monaco.languages.getLanguages().some(l => l.id === this.language)) {
      monaco.languages.register({ id: this.language })
    }

    this.$nextTick(_=>{
      // 初始化编辑器高度为容器的实际高度
      this.editorHeight = this.$el.offsetHeight;
      this.initHeight = this.editorHeight // 记录初始高度
    });

    // 添加全局事件监听
    document.addEventListener('mousemove', this.throttledResize)
    document.addEventListener('mouseup', this.stopResize)
  },
  beforeDestroy() {
    // 移除事件监听
    document.removeEventListener('mousemove', this.throttledResize)
    document.removeEventListener('mouseup', this.stopResize)
  },
  methods: {
    getFileLanguage(filename = '') {
      const ext = filename.split('.').pop().toLowerCase()
      const languageMap = {
        js: 'javascript',
        jsx: 'javascript',
        ts: 'typescript',
        tsx: 'typescript',
        html: 'html',
        css: 'css',
        less: 'less',
        scss: 'scss',
        json: 'json',
        md: 'markdown',
        vue: 'vue',
        py: 'python',
        java: 'java',
        xml: 'xml',
        sql: 'sql'
      }
      return languageMap[ext] || 'plaintext'
    },
    /**
     * 开始调整高度
     * @param e
     */
    startResize(e) {
      this.isResizing = true;
      this.isDragging = true; // 开始拖拽，将高度切换为动态调整
      this.startY = e.clientY;
      this.startHeight = this.editorHeight;

      // 阻止默认行为
      e.preventDefault();
    },
    /**
     * 调整高度
     * @param e
     */
    handleResize(e) {
      if (!this.isResizing) return;

      const deltaY = e.clientY - this.startY;
      // this.editorHeight = Math.max(200, this.startHeight + deltaY); // 更新高度
      this.editorHeight = Math.max(this.initHeight, this.startHeight + deltaY); // 不能低于初始高度
      // 防止文本选中
      e.preventDefault();
    },
    /**
     * 停止调整高度
     */
    stopResize() {
      this.isResizing = false;
    },
  }
}
</script>

<style scoped>
.file-editor-container {
    width: 100%;
    height: 100%;
    border: 1px solid #DCDFE6;
    border-radius: 4px;
    padding: 4px;
}

.resize-handle {
    position: absolute;
    right: 10px;
    bottom: 0;
    width: 10px;
    height: 10px;
    cursor: se-resize;
    background: linear-gradient(135deg, transparent 50%, #ccc 50%);
}
</style>
